package com.atguigu.rabbitmq.producer.config;

import com.alibaba.fastjson2.JSON;
import com.atguigu.rabbitmq.producer.entiry.GlobalCorrelationData;
import com.atguigu.rabbitmq.producer.service.RabbitMQService;
import jakarta.annotation.PostConstruct;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class RabbitTemplateConfiguration1 implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback {

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Autowired
    RedisTemplate<String,String> redisTemplate;

    @Autowired
    RabbitMQService rabbitService;

    @PostConstruct
    public void init(){
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }

    /**
     * 交换机都找不到 重试三次 然后记录
     * @param correlationData 发送内容
     * @param ack 发送是否成功状态 true：成功 false：失败
     * @param errMsg 失败信息
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String errMsg) {
        long time = System.currentTimeMillis();
        System.out.println("[" + time +  "] ============发送确认============"); // 添加时间戳
        if(!ack){
            GlobalCorrelationData globalCorrelationData = (GlobalCorrelationData)correlationData;
            retry(globalCorrelationData);
        }else {
            System.out.println("发送成功");
            System.out.println();
        }
    }

    /**
     * 交换机输入正确，但是路由输入错误、找不到路由发生错误  重试三次
     * @param returnedMessage 错误信息返回，只有ID有用，可以根据ID到redis中寻找完整的数据
     */
    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        long time = System.currentTimeMillis();
        System.out.println("[" + time + "] ============投递失败============"); // 添加时间戳
        String msgId = returnedMessage.getMessage().getMessageProperties().getHeader("spring_returned_message_correlation");

        String coJsonString = redisTemplate.opsForValue().get(msgId);
        GlobalCorrelationData globalCorrelationData = JSON.parseObject(coJsonString, GlobalCorrelationData.class);
        Boolean isDelay = globalCorrelationData.getIsDelay();
        // 如果isDelay 等于false(默认值) 就不是延迟队列 可以循环执行 ，如果是延迟队列就不循环执行
        if (!isDelay){
            retry(globalCorrelationData);
        }

}

    /**
     * 重试方法
     * @param globalCorrelationData 完整的对象数据
     */
    private void retry(GlobalCorrelationData globalCorrelationData) {
        // 重新发送消息 获取上一次的值加1， 放在当前对象中。如果超过三次就记录日志手动处理
        Integer reCount = globalCorrelationData.getReCount();
        if(reCount<3){
            reCount++;
            System.out.println("==============消息重发第："+reCount+"次============");
            globalCorrelationData.setReCount(reCount);// 更新重试次数
            // 发送
            rabbitService.sendMsg(globalCorrelationData.getExchange(),globalCorrelationData.getRoutingKey(),globalCorrelationData.getContent(),globalCorrelationData);
        }else {
            System.out.println("===============重试次数耗尽================");
            // 这里可以用日志记录，然后手动处理
        }
    }
    }

